/*
 * main.c
 *
 *  Created on: Nov 29, 2012
 *      Author: Andrey Belomutskiy
 */

#include "main.h"
#include "board.h"
#include "rficonsole.h"
#include "rfirtc.h"

#define TEST_PWMD PWMD4
#define TIM4_CH1_PB6_PIN 6
#define TIM4_CH4_PB9_PIN 9
#define FREQ (2 * 62500)

int pwmCounter = 0;


/*
 * PWM cyclic callback.
 */
static void pwmpcb(PWMDriver *pwmp) {

  (void)pwmp;

  chSysLockFromIsr();
  pwmCounter++;

  if(pwmCounter % 2 == 0 ) {
	  pwmEnableChannel(&TEST_PWMD, 3, PWM_FRACTION_TO_WIDTH(&TEST_PWMD, 1, 1));
  } else {
	  pwmEnableChannel(&TEST_PWMD, 3, PWM_FRACTION_TO_WIDTH(&TEST_PWMD, 1, 0));
  }

  chSysUnlockFromIsr();
}

/*
 * PWM configuration structure.
 * Cyclic callback enabled, channels 1 and 4 enabled without callbacks,
 * the active state is a logic one.
 */
static PWMConfig pwmcfg = {
  FREQ,                                    /* PWM clock frequency.   */
  2,                                    /* PWM period (in ticks).    */
  pwmpcb,
  {
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},
    {PWM_OUTPUT_DISABLED, NULL},
    {PWM_OUTPUT_DISABLED, NULL},
    {PWM_OUTPUT_ACTIVE_HIGH, NULL}
  },
  /* HW dependent part.*/
  0
};


/**
 * blinking thread to show that we are alive
 */
static WORKING_AREA(blinkingThreadStack, 128);

void blinkingThread(void *arg) {
	while (TRUE) {
		palSetPad(GPIOD, GPIOD_LED5); // red - blinks via thread
		chThdSleepMilliseconds(100);
		palClearPad(GPIOD, GPIOD_LED5); // red - blinks via thread
		chThdSleepMilliseconds(100);
	}
}

struct TimesSnapshot {
	long pwmCounter;
	long chTime;
	long rtcTime;
};
typedef struct TimesSnapshot TimesSnapshot;

void grabTimes(TimesSnapshot *sn) {
	chSysLock(); // trying to be as atomic as I can be
	sn->pwmCounter = pwmCounter;
	sn->chTime = chTimeNow();
	sn->rtcTime = currentTimeMillis();
	chSysUnlock();
}

int main(void) {
	halInit();
	chSysInit();

	palSetPad(GPIOD, GPIOD_LED3); // orange - constant ON

	chThdCreateStatic(blinkingThreadStack, sizeof(blinkingThreadStack),
			NORMALPRIO, blinkingThread, NULL);

	initConsole();

	  /*
	   * Initializes the PWM driver 4
	   */
	  pwmStart(&TEST_PWMD, &pwmcfg);
	  palSetPadMode(GPIOB, TIM4_CH1_PB6_PIN, PAL_MODE_ALTERNATE(2));  /* PB6 */
	  palSetPadMode(GPIOB, TIM4_CH4_PB9_PIN, PAL_MODE_ALTERNATE(2));  /* PB9 */


    pwmEnableChannel(&TEST_PWMD, 0, PWM_FRACTION_TO_WIDTH(&TEST_PWMD, 2, 1));

    chThdSleepMilliseconds(5000); // five secs for things to settle down
    print("Running test\r\n");
    TimesSnapshot before;
    grabTimes(&before);
    chThdSleepMilliseconds(1000); // does not matter how precise sleep is - we measure relative values

    TimesSnapshot after;
    grabTimes(&after);

    long rtcDiff = after.rtcTime - before.rtcTime;
    long chDiff = after.chTime - before.chTime;
    long pwmDiff = after.pwmCounter - before.pwmCounter;

    float pwmRatio = 1.0 * pwmDiff / rtcDiff;
    float chRatio  = 1.0 *  chDiff / rtcDiff;

    // todo: need function to print float values
    print("pwmRatio = %d\r\n", (int)(pwmRatio * 10000));
    print(" chRatio = %d\r\n", (int)( chRatio * 10000));


	while (TRUE) {
		palSetPad(GPIOD, GPIOD_LED6); // blue - blinks via main method
		chThdSleepMilliseconds(100);
		palClearPad(GPIOD, GPIOD_LED6); // blue - blinks via main method
		chThdSleepMilliseconds(100);
	}
	return 0;
}

